/*================================================================
 *   Copyright (C) 2021 All rights reserved.
 *   
 *   文件名称：log.cc
 *   创 建 者：汉森伯逸
 *   创建日期：2021年02月27日
 *   描    述：
 *
 *================================================================*/

#include <algorithm>
#include <cctype>
#include <iostream>
#include <map>
#include <memory>
#include <functional>
#include <cstring>
#include <ctime>
#include <ostream>
#include <sstream>
#include <cstdarg>
#include <cstdio>
#include <stdexcept>
#include <unordered_map>
#include <vector>
#include <yaml-cpp/node/node.h>
#include <yaml-cpp/node/parse.h>

#include "log.h"
#include "config.h"
#include "thread.h"

static hsby::Mutex g_std_cout_mutex;

namespace hsby{

/**
 * @brief 日志事件构造函数
 */
LogEvent::LogEvent(
            std::shared_ptr<Logger> logger,
            LogLevel::Level level,
            const char *mFile, int32_t mLine,
            uint32_t mElapse,
            uint32_t mThreadId,
            const std::string& mThreadName,
            uint32_t mFiberId,
            uint64_t mTime)
            :
            m_file(mFile),
            m_logger(logger) ,
            m_line(mLine),
            m_elapse(mElapse),
            m_threadId(mThreadId),
            m_threadName(mThreadName),
            m_fiberID(mFiberId),
            m_time(mTime),
            m_level(level){
}

void LogEvent::format(const char* fmt, ...) {
    va_list al;
    va_start(al, fmt);
    format(fmt, al);
    va_end(al);
}

void LogEvent::format(const char* fmt, va_list al) {
    char* buf = nullptr;
    int len = vasprintf(&buf, fmt, al);
    if(len != -1) {
        m_ss << std::string(buf, len);
        free(buf);
    }
}

LogEventWrap::LogEventWrap(LogLevel::Level level, const LogEvent::Ptr &event) :
        m_level(level), m_event(event) {
}

LogEventWrap::~LogEventWrap() {
    if (!m_event) {
        return;
    }
    m_event->getLogger()->Log( m_level, m_event);
}

std::stringstream& LogEventWrap::getSS(){
    return m_event->getSS();
}

const LogEvent::Ptr &LogEventWrap::getEvent() const {
    return m_event;
}




const char* LogLevel::ToString(LogLevel::Level level){
#define CASE(name)          \
    case LogLevel::name:    \
        return #name;       \
        break;

    switch(level){
        CASE(DEBUG)
        CASE(INFO)
        CASE(WARN)
        CASE(ERROR)
        CASE(FATAL)
#undef CASE
    default:
        return "UNKNOW";
    }
}

LogLevel::Level LogLevel::ParseFromString(std::string str){
    std::transform(str.begin(), str.end(), str.begin(), ::tolower);
    std::unordered_map<std::string, LogLevel::Level> mp_str_level{
        {"UNKNOW", LogLevel::UNKNOW},
        {"unknow", LogLevel::UNKNOW},
        {"DEBUG", LogLevel::DEBUG},
        {"INFO", LogLevel::INFO},
        {"WARN", LogLevel::WARN},
        {"ERROR", LogLevel::ERROR},
        {"FATAL", LogLevel::FATAL},
        {"info", LogLevel::INFO},
        {"warn", LogLevel::WARN},
        {"debug", LogLevel::DEBUG},
        {"error", LogLevel::ERROR},
        {"fatal", LogLevel::FATAL}
    };
    auto it = mp_str_level.find(str);
    if (it != mp_str_level.end())
        return it->second;
    return LogLevel::UNKNOW;
}




void LogAppender::setFormatter(LogFormatter::Ptr formatter){
    MutexType::WriteLockGuardType wlock(m_mutex);
    m_formatter = formatter;
}
LogFormatter::Ptr LogAppender::getFormatter(){
    MutexType::ReadLockGuardType rlock(m_mutex);
    return m_formatter;
}

void LogAppender::setDefaultFormatter(LogFormatter::Ptr formatter){
    MutexType::WriteLockGuardType wlock(m_mutex);
    m_defaultFormatter = formatter;
}

LogFormatter::Ptr LogAppender::getDefaultFormatter(){
    MutexType::ReadLockGuardType rlock(m_mutex);
    return m_defaultFormatter;
}

bool LogAppender::hasFormatter() {
    MutexType::ReadLockGuardType rlock(m_mutex);
    return !!m_formatter;
}


    Logger::Logger(const std::string& name) : m_name(name), m_level(LogLevel::UNKNOW){
    m_level = hsby::LogLevel::UNKNOW;
    m_default_formatter.reset(new LogFormatter("%d{%Y-%m-%d %X}%T%N&%t%T%F%T%p%T%c%T%f:%l%T%m{DefaultPattern}%n"));
}

void Logger::addAppender(LogAppender::Ptr appender){
    MutexType::WriteLockGuardType wlock(rw_mutex_);

//    if (typeid(appender) == typeid(StdoutLogAppender)){
//        if (hasStdoutAppender) return;
//        hasStdoutAppender = true;
//    }

    /*
     * @brief 如果输出地没有自己到formater，则设置默认formatter
     */
    if (!appender->hasFormatter()){
        appender->setDefaultFormatter(m_default_formatter);
    }

    m_appenders.push_back(appender);
}

void Logger::delAppender(LogAppender::Ptr appender){
    MutexType::WriteLockGuardType wlock(rw_mutex_);

    auto it = m_appenders.begin();
    while(it != m_appenders.end()){
        if (*it == appender){
//            if (typeid(*it) == typeid(StdoutLogAppender))
//                hasStdoutAppender = false;
            m_appenders.erase(it);
            break;
        }
        it++;
    }
}

void Logger::clearAppender(){
    MutexType::WriteLockGuardType wlock(rw_mutex_);

    m_appenders.clear();
//    hasStdoutAppender = false;
}

void Logger::setFormatter(std::string format){
    LogFormatter::Ptr formatter(new LogFormatter(format));
    setFormatter(formatter);
}

void Logger::setFormatter(LogFormatter::Ptr formatter) {
    MutexType::WriteLockGuardType wlock(rw_mutex_);
    m_default_formatter = formatter;
}

/*
 * @brief 对每个输出地都调用它的log, 传入 Logger LogLevel 和 LogEvent
 */
void Logger::Log(LogLevel::Level level, LogEvent::Ptr event){
    MutexType::ReadLockGuardType rlock(rw_mutex_);

    if (level >= m_level){
        // 如果输出地为空，转发到根日志器
        if (!m_appenders.empty()){
            for(auto& it : m_appenders){
                it->Log(shared_from_this(), level, event);
            }
        }else if(m_root_logger){
            m_root_logger->Log(level, event);
        }
    }
}

YAML::Node Logger::toYaml(){
    MutexType::ReadLockGuardType rlock(rw_mutex_);

    YAML::Node node;
    node["name"] = m_name;
    node["level"] = LogLevel::ToString(m_level);
    if (m_default_formatter) {
        node["Format"] = m_default_formatter->getPattern();
    }
    std::vector<YAML::Node> appenders;
    for(auto& appender: m_appenders){
        appenders.push_back(appender->toYaml());
    }
    node["appender"] = appenders;
    return node;
}

LogFormatter::LogFormatter(const std::string& pattern)
    : m_pattern(pattern){
    init();
}

/**
 * @brief   获取格式化元素
 * @return  LogFormatter::FormatItem::Ptr
 * @param   pattern
 * @param   item
 * @param   str
 */

class MessageFormatItem : public LogFormatter::FormatItem{
public :
    MessageFormatItem(const std::string& str) {}

    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getContent();
    }
};

class  ElapseFormatItem: public LogFormatter::FormatItem{
public :
    ElapseFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getElapse();
    }
};

class ThreadIdFormatItem: public LogFormatter::FormatItem{
public :
    ThreadIdFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getThreadId();
    }
};

class ThreadNameFormatItem: public LogFormatter::FormatItem{
public :
    ThreadNameFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getThreadName();
    }
};


    class FiberIdFormatItem: public LogFormatter::FormatItem{
public :
    FiberIdFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getFiberId();
    }
};

class FilenameFormatItem: public LogFormatter::FormatItem{
public :
    FilenameFormatItem(const std::string str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getFile();
    }
};

class LineFormatItem: public LogFormatter::FormatItem{
public :
    LineFormatItem(const std::string str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getLine();
    }
};

class LevelFormatItem : public LogFormatter::FormatItem{
public :
    LevelFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << LogLevel::ToString(level);
    }
};

class  NameFormatItem: public LogFormatter::FormatItem{
public :
    NameFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << event->getLogger()->getName();
    }
};

class DataTimeFormatItem: public LogFormatter::FormatItem{
public :
    DataTimeFormatItem(const std::string format) : m_format(format){}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        char buf[64];
        time_t t = time(0);
        struct tm *tm = localtime(&t);
        strftime(buf, sizeof(buf), m_format.c_str(), tm);
        os << buf;
    }
private:
    std::string m_format;
};

class StringFormatItem: public LogFormatter::FormatItem{
public :
    StringFormatItem(const std::string& str) : m_str(str){}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << m_str;
    }
    std::string m_str;
};

class SplitFormatItem: public LogFormatter::FormatItem{
public :
    SplitFormatItem(const std::string& str) {}
    void Format(std::shared_ptr<Logger> logger, std::ostream& os, LogLevel::Level level, LogEvent::Ptr event) override {
        os << "|";
    }
};

/**
 * @brief 解析日志模式
 */
LogFormatter::FormatItem::Ptr LogFormatter::GetFormatItem(const std::string& pattern, const std::string& item, const std::string& fmt) {
    static std::map<std::string, std::function<FormatItem::Ptr(const std::string& str)> > s_format_items = {
#define MAP_ITEM(str, C) \
        {str, [](const std::string& fmt_){ return FormatItem::Ptr(new C(fmt_));}}
        MAP_ITEM("m", MessageFormatItem),       // "%m" : 消息
        MAP_ITEM("p", LevelFormatItem),         // "%p" : 日志等级
        MAP_ITEM("r", ElapseFormatItem),        // "%r" : 累计毫秒数
        MAP_ITEM("c", NameFormatItem),          // "%c" : 日志名称
        MAP_ITEM("t", ThreadIdFormatItem),      // "%t" : 线程Id
        MAP_ITEM("N", ThreadNameFormatItem),    // "%N" : 线程名称
        MAP_ITEM("n", StringFormatItem),        // "%n" : 换行
        MAP_ITEM("d", DataTimeFormatItem),      // "%d" : 日期
        MAP_ITEM("f", FilenameFormatItem),      // "%f" : 文件名
        MAP_ITEM("l", LineFormatItem),          // "%l" : 行号
        MAP_ITEM("T", SplitFormatItem),         // "%T" : 分隔符"|"
        MAP_ITEM("F", FiberIdFormatItem)        // "%F" : 协程Id
#undef MAP_ITEM
    };
    auto it = s_format_items.find(item);
    if (it == s_format_items.end())
        throw std::logic_error("formatter pattern :\""+pattern+"\" is invalid");
    return it->second(fmt);
}

/*
 * @brief 解析模式的元素，主要是解析出m_pattern中需要被格式化的元素，将他们压入m_items
 */
void LogFormatter::init(){
    std::vector<std::tuple<std::string, std::string, int> > vec;
    std::string nstr;
    for(size_t i = 0; i < m_pattern.size(); ++i){
        if (m_pattern[i] != '%'){
            nstr.append(1, m_pattern[i]);
            continue;
        }

        // 如果走到这里说明是 "%%"
        if (i+1 < m_pattern.size() && m_pattern[i+1] == '%'){
            nstr.append(1, '%');
            i++;
            continue;
        }

        // 下面解析str和fmt, 例如："%d [%p] %f:%l %m %n"
        int fmt_status = 0;
        size_t fmt_begin = 0;

        std::string str;    // 查找对应的FormatItem
        std::string fmt;    // fmt将作为传给FormatItem的参数

        size_t j;
        for(j = i+1; j <= m_pattern.size(); ++j){

            // 如果这是结束位置, 或者本符号是非字母, str结束
            if (j == m_pattern.size() || (fmt_status == 0 && !isalpha(m_pattern[j]) && m_pattern[j] != '{' && m_pattern[j] != '}')) {
                str = m_pattern.substr(i+1, j-i-1);
                break;
            }

            // 如果遇到'{', 开始解析格式
            if (fmt_status == 0 && m_pattern[j] == '{'){
                str = m_pattern.substr(i+1, j-i-1);
                fmt_status = 1;
                fmt_begin = j+1;
                continue;
            }

            // 如果遇到'}', 格式解析结束
            if (fmt_status == 1 && m_pattern[j] == '}'){
                fmt = m_pattern.substr(fmt_begin, j-fmt_begin);
                fmt_status = 0;
                j++;
                break;
            }

        }

        if(fmt_status == 0){
            if (!nstr.empty()){
                vec.push_back(std::make_tuple(nstr, "", 0));
                nstr.clear();
            }
            vec.push_back(std::make_tuple(str, fmt, 1));
            i = j-1;
        }else if(fmt_status == 1) {
            std::cout << "pattern parse error: " << m_pattern
                      << " - " << m_pattern.substr(i)
                      << std::endl;
            throw std::logic_error("formatter pattern :\""+m_pattern+"\" is invalid");
            vec.push_back(std::make_tuple("<<pattern_error>>", fmt, 0));
        }
    }
    if (!nstr.empty()){
        vec.push_back(std::make_tuple(nstr, "", 0));
    }

    for(auto& it : vec){
        if (std::get<2>(it) == 0){
            m_items.push_back(FormatItem::Ptr(new StringFormatItem(std::get<0>(it))));
        }else{
            try {
                m_items.push_back(GetFormatItem(m_pattern, std::get<0>(it), std::get<1>(it)));
            }catch (...) {
                m_items.push_back(StringFormatItem::Ptr(new StringFormatItem("{invalid Format item<" + std::get<0>(it) + ">}")));
                throw;
            }
        }
    }

}

/*
 * @brief 格式化，返回字符串
 */
std::string LogFormatter::format(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::Ptr event){
    std::stringstream ss;
    for(auto& it : m_items){
        it->Format(logger, ss, level, event);
    }
    ss << std::endl;
    return ss.str();
}

/*
 * @brief 格式化，返回流
 */
std::ostream& LogFormatter::format(std::ostream& os, std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::Ptr event) {
    for(auto& item : m_items) {
        if (!item) {
            continue;
        }
        item->Format(logger, os, level, event);
    }
    os << std::endl;
    os.flush();
    return os;
}

void StdoutLogAppender::Log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::Ptr event){
    if (level >= m_level){
        MutexType::ReadLockGuardType rlock(m_mutex);
        LogFormatter::Ptr formatter = hasFormatter() ? m_formatter : m_defaultFormatter;
        Mutex::LockGuardType lock(g_std_cout_mutex);
        formatter->format(std::cout, logger, level, event);
    }
}

YAML::Node StdoutLogAppender::toYaml(){
    MutexType::ReadLockGuardType rlock(m_mutex);
    YAML::Node node;
    node["type"] = "StdoutLogappender";
    if (hasFormatter())
        node["Format"] = m_formatter->getPattern();
    node["level"] = LogLevel::ToString(m_level);
    return node;
}



FileLogAppender::FileLogAppender(const std::string filename) 
    : m_filename(filename){
    reopen();
}

void FileLogAppender::Log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::Ptr event){
    if(level >= m_level) {
        reopen();
        MutexType::ReadLockGuardType rlock(m_mutex);
        LogFormatter::Ptr formatter = hasFormatter() ? m_formatter : m_defaultFormatter;
        if(!formatter->format(m_filestream, logger, level, event)) {
            std::cout << "FileLogAppender::log error Logger->name=" << logger->getName() << std::endl;
        }
    }
}

bool FileLogAppender::reopen(){
    MutexType::WriteLockGuardType rlock(m_mutex);
    if (m_filestream){
        m_filestream.close();
    }
    m_filestream.open(m_filename, std::ios::app);
    return !!m_filestream;
}

YAML::Node FileLogAppender::toYaml(){
    MutexType::ReadLockGuardType rlock(m_mutex);
    YAML::Node node;
    node["type"] = "FileLogappender";
    if (hasFormatter())
        node["Format"] = m_formatter->getPattern();
    node["file"] = m_filename;
    node["level"] = LogLevel::ToString(m_level);
    return node;
}




LoggerManager::LoggerManager() {
    MutexType::LockGuardType lock(m_mutex);
    m_root.reset(new Logger("root"));
    m_root->addAppender(std::make_shared<StdoutLogAppender>());
    m_loggers[m_root->getName()] = m_root;
    init();
}

void LoggerManager::init(){
    
}

YAML::Node LoggerManager::toYaml(){
    MutexType::LockGuardType lock(m_mutex);
    YAML::Node node;
    std::vector<YAML::Node> loggers;
    for(auto it : m_loggers){
        loggers.push_back(it.second->toYaml());
    }
    node["logs"] = loggers;
    return node;
}

Logger::Ptr LoggerManager::getLogger(const std::string &name) {
    MutexType::LockGuardType lock(m_mutex);
    auto it = m_loggers.find(name);
    if (it != m_loggers.end())
        return it->second;
    Logger::Ptr logger(new Logger(name));
    logger->m_root_logger = m_root;
    m_loggers[name] = logger;
    return logger;
}




struct LogAppenderDefine{
    int type;
    LogLevel::Level level = LogLevel::UNKNOW;
    std::string format;
    std::string file;

    std::string toString() const {
        std::stringstream ss;
        ss << "    LogAppenderDefine{" << std::endl;
        ss << "      type=" << type << std::endl;
        ss << "      level=" << level << std::endl;
        ss << "      Format=" << format << std::endl;
        ss << "      file=" << file << std::endl;
        ss << "    }" << std::endl;
        return ss.str();
    }

    bool operator==(const LogAppenderDefine& oth) const {
        return type == oth.type
            && level == oth.level
            && format == oth.format
            && file == oth.file;
    }

    static int parseType(std::string str){
        /*
         * @brief 解析类型时不分大小写
         */
        std::transform(str.begin(), str.end(), str.begin(), ::tolower);
        std::map<std::string, int> mp_str_int;
        mp_str_int.insert({"stdoutlogappender", 0});
        mp_str_int.insert({"stdout", 0});
        mp_str_int.insert({"filelogappender", 1});
        mp_str_int.insert({"file", 1});
        auto it = mp_str_int.find(str);
        if (it != mp_str_int.end()){
            return it->second;
        }
        return 0;
    };
};

struct LoggerDefine{
    std::string name;
    LogLevel::Level level = LogLevel::Level::UNKNOW;
    std::string format;
    std::vector<LogAppenderDefine> appenders;

    std::string toString() const{
        std::stringstream ss;
        ss << "LoggerDefine{ " << std::endl;
        ss << "  name=" << name << std::endl;
        ss << "  level=" << level << std::endl;
        ss << "  Format=" << format << std::endl;
        ss << "  appenders{" << std::endl;
        for (size_t i = 1; i <= appenders.size(); i++){
            ss <<"    " << "[" << i << "] " << std::endl;
            ss<< appenders[i-1].toString();
        }
        ss << "  }" << std::endl;
        ss << "}" << std::endl;
        return ss.str();
    }

    bool operator==(const LoggerDefine& oth) const {
        return name == oth.name
            && level == oth.level
            && format == oth.format
            && appenders == oth.appenders;
    }

    bool operator<(const LoggerDefine& r) const {
        return name < r.name;
    }
};

/*
 * @brief 配置支持LoggerDefine yml-->LoggerDefine
 */
template<>
class LexicalCast<std::string, LoggerDefine>{
public:
    LoggerDefine operator()(std::string yml){
        YAML::Node node = YAML::Load(yml);
        LoggerDefine ld;

        if (!node.IsMap()){
            std::stringstream ss;
            ss << "LexicalCast YAML eroor: " << node;
            std::cout << ss.str();
            throw std::logic_error(ss.str());
        }

        if (node["name"].IsDefined())
            ld.name = node["name"].as<std::string>();
        else {
            std::cout << "log config error: name is null, " << node << std::endl;
            throw std::logic_error("log config name is null");
        }
        if (node["Format"].IsDefined())
            ld.format = node["Format"].as<std::string>();

        // 设置等级
        ld.level = LogLevel::UNKNOW;
        if (node["level"].IsDefined())
            ld.level = LogLevel::ParseFromString(node["level"].as<std::string>());

        // 设置appender
        std::vector<LogAppenderDefine> apds;
        if (node["appender"].IsDefined()){
            for(auto ymlApd : node["appender"]){
                LogAppenderDefine apd;

                // 默认stdout
                apd.type = LogLevel::UNKNOW;
                if (ymlApd["type"].IsDefined())
                    apd.type = LogAppenderDefine::parseType(ymlApd["type"].as<std::string>());

                if (ymlApd["Format"].IsDefined())
                    apd.format = ymlApd["Format"].as<std::string>();

                if (ymlApd["level"].IsDefined())
                    apd.level = LogLevel::ParseFromString(ymlApd["level"].as<std::string>());

                // 如果是fileappender，必须提供file参数
                if (apd.type == 1){
                    if (ymlApd["file"].IsDefined())
                        apd.file = ymlApd["file"].as<std::string>();
                    else {
                        std::cout << "log config error: fileappender file is null, " << ymlApd << std::endl;
                        continue;
                    }
                }
                ld.appenders.push_back(apd);
            }
        }
        return ld;
    }
};
/*
 * @brief 配置支持LoggerDefine LoggerDefine-->yml
 */
template<>
class LexicalCast<LoggerDefine, std::string>{
public:
     std::string operator()(LoggerDefine i){
        YAML::Node n;
        n["name"] = i.name;
        if(i.level != LogLevel::UNKNOW) {
            n["level"] = LogLevel::ToString(i.level);
        }
        if(!i.format.empty()) {
            n["formatter"] = i.format;
        }

        for(auto& a : i.appenders) {
            YAML::Node na;
            if(a.type == 1) {
                na["type"] = "FileLogAppender";
                na["file"] = a.file;
            } else if(a.type == 2) {
                na["type"] = "StdoutLogAppender";
            }
            if(a.level != LogLevel::UNKNOW) {
                na["level"] = LogLevel::ToString(a.level);
            }

            if(!a.format.empty()) {
                na["formatter"] = a.format;
            }

            n["appenders"].push_back(na);
        }
        std::stringstream ss;
        ss << n;
        return ss.str();
    }
};


ConfigVar<std::set<LoggerDefine>>::Ptr g_log_defines =
    Config::Lookup("logs", std::set<LoggerDefine>(), "logs config");

struct LogIniter{
    LogIniter(){
        auto cb = [](const std::set<LoggerDefine>& old_defs, const std::set<LoggerDefine>& new_defs){
                    for(auto& def : new_defs){
                        auto it = old_defs.find(def);
                        Logger::Ptr logger;

                        if (!(def == *it)){
                            logger = HSBY_LOG_NAME(def.name);
                        }else{
                            continue;
                        }
                        if (!logger) continue;

                        // 设置level
                        logger->setLevel(def.level);

                        // 设置format
                        if (!def.format.empty())
                            logger->setFormatter(def.format);

                        // 设置appender
                        logger->clearAppender();
                        for(auto& a : def.appenders){
                            LogAppender::Ptr app;

                            if (a.type == 0){
                                app.reset(new StdoutLogAppender());
                            }else if (a.type == 1){
                                app.reset(new FileLogAppender(a.file));
                            }

                            // 设置level
                            app->setLevel(a.level);

                            // 设置formatter
                            if (!a.format.empty()){
                                app->setFormatter(std::make_shared<LogFormatter>(a.format));
                            }


                            logger->addAppender(app);
                        }
                    }

                    for(auto& def : old_defs){
                        auto it = new_defs.find(def);
                        if (it == new_defs.end()){
                            // 删除
                            auto logger = HSBY_LOG_NAME(def.name);
                            logger->setLevel((LogLevel::Level)100);
                            logger->clearAppender();
                         }
                     }
                };
        g_log_defines->AddListener(cb);
    }
};

static LogIniter __g_loginiter;

} // namespace hsby
